#include "icl.h"
#include <string>

namespace icl
{
	uint32_t getPlatformIDs(cl_platform_id **ret, size_t *ret_size)
	{
		cl_int err = CL_SUCCESS;
		cl_uint size = 0;

		cl_platform_id t1;
		err |= clGetPlatformIDs(1, &t1, &size);
		if (err != CL_SUCCESS)
			return err;
		if (size < 1)
			return ERR_PLATFORM_NOT_FOUND;
		cl_platform_id *platform = new cl_platform_id[size];
		err |= clGetPlatformIDs(size, platform, &size);

		*ret = platform;
		*ret_size = (size_t)size;
		return NO_ERR;
	}

	uint32_t getPlatformInfo(cl_platform_id id, PlatformInfo *ret)
	{
		cl_int err = CL_SUCCESS;
		size_t size = 0;

		ret->profile = NULL;
		ret->version = NULL;
		ret->name = NULL;
		ret->vendor = NULL;
		ret->extensions = NULL;

		char buffer[8];
		err = clGetPlatformInfo(id, CL_PLATFORM_PROFILE, 7, buffer, &size);
		if (err == CL_SUCCESS)
		{
			char *profile = new char[size + 1];
			clGetPlatformInfo(id, CL_PLATFORM_PROFILE, size, profile, &size);
			ret->profile = profile;
		}

		clGetPlatformInfo(id, CL_PLATFORM_VERSION, 7, buffer, &size);
		if (err == CL_SUCCESS)
		{
			char *version = new char[size + 1];
			clGetPlatformInfo(id, CL_PLATFORM_VERSION, size, version, &size);
			ret->version = version;
		}

		clGetPlatformInfo(id, CL_PLATFORM_NAME, 7, buffer, &size);
		if (err == CL_SUCCESS)
		{
			char *name = new char[size + 1];
			clGetPlatformInfo(id, CL_PLATFORM_NAME, size, name, &size);
			ret->name = name;
		}

		clGetPlatformInfo(id, CL_PLATFORM_VENDOR, 7, buffer, &size);
		if (err == CL_SUCCESS)
		{
			char *vendor = new char[size + 1];
			clGetPlatformInfo(id, CL_PLATFORM_VENDOR, size, vendor, &size);
			ret->vendor = vendor;
		}

		clGetPlatformInfo(id, CL_PLATFORM_EXTENSIONS, 7, buffer, &size);
		if (err == CL_SUCCESS)
		{
			char *extensions = new char[size + 1];
			clGetPlatformInfo(id, CL_PLATFORM_EXTENSIONS, size, extensions, &size);
			ret->extensions = extensions;
		}

		return NO_ERR;
	}

	const char *getErrMessage(uint32_t err)
	{
		switch (err) {
			case ERR_PLATFORM_NOT_FOUND:
				return "Cannot found any OpenCL platform";
			default:
				return ("Error code " + std::to_string(err)).c_str();
		}
	}
}
